/*
 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package java.lang.instrument;

import  java.security.ProtectionDomain;

/*
 * Copyright 2003 Wily Technology, Inc.
 */

/**
 * 代理提供此接口的实现以转换类文件。
 * 转换发生在JVM定义类之前。
 * <P>
 * 注意术语<i>类文件</i>的使用如<cite>Java&trade; 虚拟机规范</cite>第3.1节中定义，
 * 指类文件格式的字节序列，无论它们是否驻留在文件中。
 *
 * @see     java.lang.instrument.Instrumentation
 * @see     java.lang.instrument.Instrumentation#addTransformer
 * @see     java.lang.instrument.Instrumentation#removeTransformer
 * @since   1.5
 */

public interface ClassFileTransformer {
    /**
     * 此方法的实现可以转换提供的类文件并返回新的替换类文件。
     *
     * <P>
     * 有两种转换器，由{@link java.lang.instrument.Instrumentation#addTransformer(ClassFileTransformer,boolean)}
     * 的<code>canRetransform</code>参数确定：
     *  <ul>
     *    <li><i>支持重新转换</i>的转换器，添加时<code>canRetransform</code>为true
     *    </li>
     *    <li><i>不支持重新转换</i>的转换器，添加时<code>canRetransform</code>为false
     *        或使用{@link java.lang.instrument.Instrumentation#addTransformer(ClassFileTransformer)}添加
     *    </li>
     *  </ul>
     *
     * <P>
     * 一旦转换器通过{@link java.lang.instrument.Instrumentation#addTransformer(ClassFileTransformer,boolean)
     * addTransformer}注册，转换器将在每次新类定义和每次类重新定义时被调用。
     * 支持重新转换的转换器还将在每次类重新转换时被调用。
     * 新类定义的请求通过{@link java.lang.ClassLoader#defineClass ClassLoader.defineClass}
     * 或其本地等价物发出。
     * 类重新定义的请求通过{@link java.lang.instrument.Instrumentation#redefineClasses Instrumentation.redefineClasses}
     * 或其本地等价物发出。
     * 类重新转换的请求通过{@link java.lang.instrument.Instrumentation#retransformClasses Instrumentation.retransformClasses}
     * 或其本地等价物发出。
     * 转换器在处理请求期间被调用，在类文件字节被验证或应用之前。
     * 当有多个转换器时，转换通过链式调用<code>transform</code>方法来组合。
     * 也就是说，一次<code>transform</code>调用返回的字节数组成为下一次调用的输入
     * （通过<code>classfileBuffer</code>参数）。
     *
     * <P>
     * 转换按以下顺序应用：
     *  <ul>
     *    <li>不支持重新转换的转换器
     *    </li>
     *    <li>不支持重新转换的本地转换器
     *    </li>
     *    <li>支持重新转换的转换器
     *    </li>
     *    <li>支持重新转换的本地转换器
     *    </li>
     *  </ul>
     *
     * <P>
     * 对于重新转换，不支持重新转换的转换器不会被调用，
     * 而是重用之前转换的结果。在所有其他情况下，此方法会被调用。
     * 在每个分组内，转换器按注册顺序调用。
     * 本地转换器由Java虚拟机工具接口中的<code>ClassFileLoadHook</code>事件提供。
     *
     * <P>
     * 第一个转换器的输入（通过<code>classfileBuffer</code>参数）是：
     *  <ul>
     *    <li>对于新类定义，
     *        传递给<code>ClassLoader.defineClass</code>的字节
     *    </li>
     *    <li>对于类重新定义，
     *        <code>definitions.getDefinitionClassFile()</code>，其中
     *        <code>definitions</code>是{@link java.lang.instrument.Instrumentation#redefineClasses
     *         Instrumentation.redefineClasses}的参数
     *    </li>
     *    <li>对于类重新转换，
     *         传递给新类定义的字节，或者如果已重新定义，
     *         则是最后一次重新定义的字节，其中不支持重新转换的转换器
     *         所做的所有转换会自动重新应用且不变；
     *         详情请参见{@link java.lang.instrument.Instrumentation#retransformClasses
     *          Instrumentation.retransformClasses}
     *    </li>
     *  </ul>
     *
     * <P>
     * 如果实现方法确定不需要转换，应返回<code>null</code>。
     * 否则，应创建一个新的<code>byte[]</code>数组，
     * 将输入的<code>classfileBuffer</code>复制到其中，
     * 连同所有所需的转换，并返回新数组。
     * 输入的<code>classfileBuffer</code>不得被修改。
     *
     * <P>
     * 在重新转换和重新定义的情况下，
     * 转换器必须支持重新定义语义：
     * 如果转换器在初始定义期间更改的类后来被重新转换或重新定义，
     * 转换器必须确保第二个类输出类文件是第一个输出类文件的合法重新定义。
     *
     * <P>
     * 如果转换器抛出异常（且未捕获），
     * 后续转换器仍将被调用，加载、重新定义或重新转换仍将被尝试。
     * 因此，抛出异常与返回<code>null</code>具有相同效果。
     * 为了防止在转换器代码中生成未检查异常时出现意外行为，
     * 转换器可以捕获<code>Throwable</code>。
     * 如果转换器认为<code>classFileBuffer</code>不代表格式有效的类文件，
     * 应抛出<code>IllegalClassFormatException</code>；
     * 虽然这与返回null具有相同效果，但它有助于记录或调试格式损坏。
     *
     * @param loader                要转换的类的定义加载器，
     *                              如果是引导加载器则可能为<code>null</code>
     * @param className             类的名称，采用<i>Java虚拟机规范</i>中定义的
     *                              完全限定类和接口名称的内部形式。
     *                              例如，<code>"java/util/List"</code>。
     * @param classBeingRedefined   如果这是由重新定义或重新转换触发的，
     *                              则为正在重新定义或重新转换的类；
     *                              如果这是类加载，则为<code>null</code>
     * @param protectionDomain      正在定义或重新定义的类的保护域
     * @param classfileBuffer       类文件格式的输入字节缓冲区 - 不得修改
     *
     * @throws IllegalClassFormatException 如果输入不代表格式良好的类文件
     * @return  格式良好的类文件缓冲区（转换的结果），
                或者如果未执行转换则返回<code>null</code>。
     * @see Instrumentation#redefineClasses
     */
    byte[]
    transform(  ClassLoader         loader,
                String              className,
                Class<?>            classBeingRedefined,
                ProtectionDomain    protectionDomain,
                byte[]              classfileBuffer)
        throws IllegalClassFormatException;
}
